//
//  BlueManager.swift
//  YitihuaPH
//
//  Created by Kai Kang on 2019/1/15.
//  Copyright © 2019 Kai Kang. All rights reserved.
//

import Foundation
import CoreBluetooth

private var perStateContext = 0
class BlueManager: NSObject {
    static let share = BlueManager()
    
    var btManager: CBCentralManager!
    var connectedPer: CBPeripheral!
    var charateristic: CBCharacteristic!
    
    var dataSource = [CBPeripheral]()
    var discoverPeripheral: ((_ peripheral: CBPeripheral) -> Void)?
    var didUpdateValue: ((_ chara: CBCharacteristic) -> Void)?
    
    override init() {
        super.init()
        initBle()
    }
}

extension BlueManager {
    func initBle() {
        // 拦截蓝牙没有开启的系统弹窗
        let backgroundModes =  Bundle.main.infoDictionary!["UIBackgroundModes"] as! [String]
        if backgroundModes.contains("bluetooth-central") {
            btManager = CBCentralManager.init(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: 0])
        } else {
            btManager = CBCentralManager.init(delegate: self, queue: nil)
        }
    }
}

// MARK: - 自定义方法
extension BlueManager {
    // 扫描心电设备设备
    func startScan() {
        refresh(btState: "正在扫描设备")
        if connectedPer != nil {
            disconnect()
        }
        dataSource.removeAll()
        btManager.scanForPeripherals(withServices: nil, options: nil)
    }
    
    // 断开连接
    func disconnect() {
        if let per = connectedPer, (per.state == .connected || per.state == .connecting) {
            btManager.cancelPeripheralConnection(per)
            per.removeObserver(self, forKeyPath: "state")
            per.delegate = nil
            self.connectedPer = nil
        }
    }
    
    /// 连接到设备
    func connect(peripheral: CBPeripheral)  {
        disconnect()
        self.connectedPer = peripheral
        self.connectedPer.addObserver(self, forKeyPath: "state", options: .new, context: &perStateContext)
        btManager.connect(self.connectedPer, options: nil)
    }
    
    /// 发送命令
    func write(data: Data) {
        if let peripheral = connectedPer, let chara = charateristic {
            peripheral.writeValue(data, for: chara, type: .withResponse)
        }
    }
    
    // 蓝牙状态改变
    @available(iOS 10.0, *)
    func setBtStatus(_ state: CBManagerState) {
        var btStateNote = ""
        switch state {
        case .poweredOn:
            btStateNote = "蓝牙已经开启"
        case .poweredOff:
            btStateNote = "请开启蓝牙以连接到设备"
        case .unauthorized:
            btStateNote = "设备未授权"
        case .unsupported:
            btStateNote = "设备不支持"
        case .resetting:
            btStateNote = "设备在重置"
        default:
            btStateNote = "设备状态未知"
        }
        
        refresh(btState: btStateNote)
    }
    
    // 刷新状态显示
    func refresh(btState: String) {
        print(btState)
    }
}

// MARK: - CBCenter代理
extension BlueManager: CBCentralManagerDelegate {
    // 监听蓝牙状态
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if #available(iOS 10.0, *) {
            setBtStatus(central.state)
        } else {
            // Fallback on earlier versions
        }
    }
    
    // 扫描到外设
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
        
        if !dataSource.contains(peripheral), let name = peripheral.name, !name.isEmpty {
            dataSource.append(peripheral)
            
            if let discover = discoverPeripheral {
                discover(peripheral)
            }
        }
        
        if peripheral.name == "Bluetooth BP" {
            refresh(btState: "发现设备，正在连接...")
            
            self.connectedPer = peripheral
            peripheral.addObserver(self, forKeyPath: "state", options: .new, context: &perStateContext)
            
            central.connect(peripheral, options: nil)
        }
    }
    
    // 连接成功
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        peripheral.delegate = self
        peripheral.discoverServices(nil)
        central.stopScan()
        
        print("连接到: \(peripheral.name ?? "未命名")")
        
        postNotfication(Notification.Name.init("connected"))
        
        peripheral.discoverServices(nil)
    }
    
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        self.connectedPer = nil
        
        print("连接已断开，断开的设备：\(peripheral.name ?? "未命名")")
        refresh(btState: "连接已断开，重新扫描设备")
        
    }
    
    // 连接失败
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        print("连接 \(peripheral.name ?? "未命名") 失败，失败原因：\(error.debugDescription)")
        refresh(btState: "连接失败")
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "state" {
            if let per = connectedPer, per.state == .disconnected {
                btManager.cancelPeripheralConnection(connectedPer)
            }
        }
    }
}

let customerServiceUUID: String = "FFF0"
let customerCharachterUUID: String = "FFF1"
let notificationNews: String = "notifications"
func postNotfication(_ name: Notification.Name, object: Any? = nil )  {
    NotificationCenter.default.post(name: name, object: object)
}

// MARK: - CBPeripheral代理
extension BlueManager: CBPeripheralDelegate {
    // 扫描到服务
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        guard error == nil else { print("扫描服务错误，错误信息：\(error.debugDescription)"); return }
        guard let services = peripheral.services else { return }
        
        for service in services {
            print("发现服务 UUID：\(service.uuid.uuidString)")
            
            if service.uuid == CBUUID.init(string: customerServiceUUID){
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }
    
    // 扫描到特征
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        guard error == nil else { print("扫描特征错误，错误信息：\(error.debugDescription)"); return }
        guard let charas = service.characteristics else { return }
        
        for chara in charas {
            if chara.uuid.uuidString == customerCharachterUUID {
                
                self.charateristic = chara
                self.connectedPer.setNotifyValue(true, for: self.charateristic!)
            }
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
        guard error == nil else { print("接收通知错误，错误信息：\(error.debugDescription) ") ; return }
        
        // Notification has started
        if characteristic.isNotifying {
            print("开始订阅：\(characteristic)")
            peripheral.readValue(for: characteristic)
        } else { // Notification has stopped
            print("取消订阅：\(characteristic)")
            btManager.cancelPeripheralConnection(peripheral)
        }
    }
    
    // 当设备有数据返回的时候的回调方法
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        guard error == nil else { print("接收数据错误，错误信息：\(error.debugDescription) ") ; return }
        
        //        print("特征值UUID\(characteristic.uuid.uuidString) 接收到数据")
//        dispose(btData: characteristic.value)
        if let didUpdate = didUpdateValue {
            didUpdate(characteristic)
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        guard error == nil else {
            print(error.debugDescription)
            return
        }
    }
}

